package main

import (
	"fmt"
	"sync"
	"time"
)

/**
限流策略
1、计数器
2、滑动窗口
3、漏桶
4、令牌桶
*/
func main() {
	limitRate := LimitRate{
		rate:  2,               // 阈值2个
		cycle: 1 * time.Second, // 10s
	}
	limitRate.Set(limitRate.rate, limitRate.cycle)

	queue := []int{1, 2, 3}
	for _, v := range queue {
		time.Sleep(100 * time.Millisecond)
		allow := limitRate.Allow()
		fmt.Println(fmt.Sprintf("current_value:%d,deal:%t", v, allow))
	}
}

type LimitRate struct {
	rate  int           //阀值
	begin time.Time     //计数开始时间
	cycle time.Duration //计数周期
	count int           //收到的请求数
	lock  sync.Mutex    //锁
}

func (limit *LimitRate) Allow() bool {
	limit.lock.Lock()
	defer limit.lock.Unlock()

	// 判断收到请求数是否达到阀值
	if limit.count == limit.rate-1 {
		fmt.Println("当前请求数达到阀值", limit.rate)
		now := time.Now()
		// 达到阀值后，判断是否是请求周期内
		if now.Sub(limit.begin) >= limit.cycle {
			fmt.Println("重置计数器")
			limit.Reset(now)
			return true
		}
		return false
	} else {
		limit.count++
		return true
	}
}

func (limit *LimitRate) Set(rate int, cycle time.Duration) {
	limit.rate = rate
	limit.begin = time.Now()
	limit.cycle = cycle
	limit.count = 0
}

func (limit *LimitRate) Reset(begin time.Time) {
	limit.begin = begin
	limit.count = 0
}
